#include "ty_adc.h"
#include "ty_ble.h"
#include "ty_flash.h"
#include "ty_i2c.h"
#include "ty_pin.h"
#include "ty_pwm.h"
#include "ty_rtc.h"
#include "ty_spi.h"
#include "ty_system.h"
#include "ty_timer.h"
#include "ty_uart.h"
#include "tuya_ble_api.h"
#include "tuya_ble_log.h"

//#include "ty_oled.h"
#include "arch.h"
#include "co_delay.h"
#include "wdt.h"
#include "app_log.h"
#include "tuya_ble_sdk_test.h"



/*********************************************************************
 * CONSTANT
 */
#define WDT_TIMEOUT             5

/*********************************************************************
 * STRUCT
 */

/*********************************************************************
 * VARIABLE
 */
static uint8_t reason[5][8] =
{
    "POWERON",
    "SLEEP",
    "ISP",
    "USER",
    "WDT",
};

/*********************************************************************
 * FUNCTION
 */
co_power_status_t power_sleep_status_handler(void)
{
    return pmu_power_status();
}

static void power_sleep_event_handler(co_power_sleep_state_t sleep_state, co_power_status_t power_status)
{
    switch(sleep_state)
    {
        case POWER_SLEEP_ENTRY:
            SCB->CPACR &= ~0x00F00000; // disable float-point calculation
            break;

        case POWER_SLEEP_LEAVE_TOP_HALF:
        #if (TUYA_BLE_SDK_TEST || TUYA_BLE_SPP_ENABLE)
            ty_uart_init();
        #endif
            ty_uart2_init();
            SCB->CPACR |= 0x00F00000; // enable float-point calculation
            break;

        case POWER_SLEEP_LEAVE_BOTTOM_HALF:
            break;
    }
}

static void om_system_init(void)
{
    wdt_enable(0); // disable WDT
    pmu_dcdc_enable(CONFIG_INTERNAL_DCDC); // enable/disable internal DC-DC
    pmu_32k_enable_in_deep_sleep(CONFIG_32K_IN_DEEP_SLEEP); // enable/disable 32k in deep sleep mode
    pmu_select_32k(CONFIG_32K_CLOCK); // select 32k clock for stack
    pmu_xtal32m_change_param(XTAL32M_CTUNE_DEFAULT); // set load capacitance for 32M xtal
    co_power_ultra_sleep_mode_enable(CONFIG_SLEEP_MODE); // enable/disable ultra sleep mode
    co_power_sleep_enable(CONFIG_SLEEP_MODE); // enable/disable sleep mode, SWD will be closed

    gpio_open();
    pmu_pin_mode_set(0xFFFFFFF3, PMU_PIN_MODE_PU);
    pmu_pin_mode_set(0x0000000C, PMU_PIN_MODE_PD);

    rwip_init(RESET_NO_ERROR); // stack init

    rf_tx_power_set(false, 0); // set RF power

    co_power_register_user_status(power_sleep_status_handler);
    co_power_register_sleep_event(power_sleep_event_handler);

    SCB->CPACR |= 0x00F00000; // enable float-point calculation
}

uint32_t ty_system_init(uint8_t location)
{
    switch(location)
    {
        case 0: {
            om_system_init();
        #if (TUYA_BLE_SDK_TEST || TUYA_BLE_SPP_ENABLE)
            ty_uart_init();
        #endif
            //ty_uart2_init();//LOG
            ty_flash_init();
            ty_rtc_init();
            ty_system_log_init();

            TY_PRINTF("****************************************");
            TY_PRINTF("* TuYa BLE APP");
            TY_PRINTF("* Compile at %s %s", __TIME__, __DATE__);
            TY_PRINTF("****************************************");
            TY_PRINTF("Reboot reason: %s", reason[pmu_reboot_reason()]);
        } break;

        case 1: {
        #if TUYA_BLE_SDK_TEST
//            ty_oled_init();
            ty_system_exit_sleep();
        #endif
        } break;

        case 2: {
        } break;

        default: {
        } break;
    }
    return 0;
}

uint32_t ty_system_mainloop(void)
{
    tuya_ble_main_tasks_exec();
    return 0;
}

uint32_t ty_system_reset(void)
{
    sfs_cache_enable(false);
    sfs_cache_invalidate_all();
    pmu_force_reboot();
    return 0;
}

uint32_t ty_system_wdt_init(void)
{
    wdt_enable(WDT_TIMEOUT);
    return 0;
}

uint32_t ty_system_wdt_uninit(void)
{
    wdt_enable(0);
    return 0;
}

uint32_t ty_system_wdt_feed(void)
{
    wdt_keepalive();
    return 0;
}

uint32_t ty_system_log_init(void)
{
#if (TY_LOG_ENABLE||TUYA_BLE_LOG_ENABLE||TUYA_APP_LOG_ENABLE)
    elog_init();
//    elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_LVL);
    elog_start();
#endif
    return 0;
}

uint32_t ty_system_log_hexdump(const char *name, uint8_t width, uint8_t *buf, uint16_t size)
{
#if (TY_LOG_ENABLE||TUYA_BLE_LOG_ENABLE||TUYA_APP_LOG_ENABLE)
    elog_hexdump(name, width, buf, size);
#endif
    return 0;
}

uint32_t ty_system_delay_ms(uint32_t ms)
{
    co_delay_ms(ms);
    return 0;
}

uint32_t ty_system_delay_us(uint32_t us)
{
    co_delay_us(us);
    return 0;
}

uint32_t ty_system_enter_sleep(void)
{
    pmu_pin_mode_set(0x0000000C, PMU_PIN_MODE_PD);
    pmu_lowpower_allow(PMU_LP_USER);
    return 0;
}

uint32_t ty_system_exit_sleep(void)
{
    pmu_lowpower_prevent(PMU_LP_USER);
    return 0;
}

bool ty_system_is_sleep(void)
{
    return false;
}

#if TUYA_BLE_SDK_TEST
/*********************************************************
FN:
*/
uint32_t ty_system_save_pid(uint8_t* buf, uint32_t size)
{
    tuya_ble_nv_erase(BOARD_FLASH_TEST_PID_ADDR, 0x1000);
    tuya_ble_nv_write(BOARD_FLASH_TEST_PID_ADDR, buf, size+2);
    return 0;
}

/*********************************************************
FN:
*/
uint32_t ty_system_load_pid(void)
{
    uint8_t tmp_buf[TUYA_BLE_PRODUCT_ID_MAX_LEN+2] = {0};
    tuya_ble_nv_read(BOARD_FLASH_TEST_PID_ADDR, tmp_buf, TUYA_BLE_PRODUCT_ID_MAX_LEN+2);
    if(tmp_buf[0] != 0xFF) {
        tuya_ble_device_update_product_id(tmp_buf[0], tmp_buf[1], &tmp_buf[2]);
    }
    return 0;
}
#endif
